import { Md5 } from 'ts-md5';
import { FlowNode } from './../../../../../models/work-flow/flow-node';
import { delay } from 'rxjs/operators';
import { DataRegister } from './../../../../../models/data-register';
import { Subscription } from 'rxjs';
import { Tools } from './../../../../tools/tools';
import { ExceptionHandler } from './../../../../../handler/exception.handler';
import { AfterViewInit, Component, OnInit, OnDestroy } from '@angular/core';
import { BaseFieldComponent } from '../base-field/base-field.component';
import { Router } from '@angular/router';
import { NzMessageService } from 'ng-zorro-antd';
import { PermitConfig } from '../../../models';
import { UploadService } from 'src/app/services/upload.service';
import { BaseService, DataRegisterService, PageService } from 'src/app/services';
import { EventManagerService } from 'src/app/services/event-manager.service';
import { OrganizationService } from 'src/app/services/organization.service';
import { EngineService } from '../../../services/engine.service';
import { DataChangeLogService } from '../../../../../services/data-change-log.service';
import { DataChangeLog, DataChangeLogStatus } from 'src/app/models/dataChangeLog';
import { WorkflowPageService } from 'src/app/common/page-render/workflow-page-container/workflow-page.service';
import { User } from 'src/app/models';

@Component({
  selector: 'zepride-function-button',
  templateUrl: './function-button.component.html',
  styleUrls: ['./function-button.component.less', '../field.common.less']
})
export class FunctionButtonComponent extends BaseFieldComponent implements OnInit, AfterViewInit, OnDestroy {
  workflowUpdatedSub: Subscription;
  auditFinishSub: Subscription;
  flowNodeUpdateSub: Subscription;
  dataRegister: DataRegister;
  flowNode: {
    flowNodeId: string;
    nodeName: string;
    status: string;
    updateTime: number;
    flowNode: FlowNode;
  };
  orgId: string;
  sourceData: { [x: string]: any; };
  user: User;

  permitConfig: PermitConfig[] = [
    { mode: 'query', permitId: '查看', permitName: '', authObjectId: '' },
    { mode: 'edit', permitId: '编辑', permitName: '', authObjectId: '' }
  ];

  constructor(
    protected engineService: EngineService,
    protected baseSvr: BaseService,
    protected eventSvr: EventManagerService,
    protected orgSvr: OrganizationService,
    public uploadService: UploadService,
    protected msg: NzMessageService,
    private router: Router,
    private dataChangeSvr: DataChangeLogService,
    private wSvr: WorkflowPageService,
    private pageSvr: PageService,
    protected dataRegisterSvr: DataRegisterService
  ) {
    super(engineService, baseSvr, eventSvr, orgSvr, uploadService, msg, dataRegisterSvr);
    this.orgId = localStorage.getItem('orgid');
    this.user = JSON.parse(localStorage.getItem('userInfo'));
  }
  ngOnDestroy() {
    if (this.workflowUpdatedSub) {
      this.workflowUpdatedSub.unsubscribe();
    }
    if (this.auditFinishSub) {
      this.auditFinishSub.unsubscribe();
    }
    if (this.modelChange$) {
      this.modelChange$.unsubscribe();
    }
    if (this.flowNodeUpdateSub) {
      this.flowNodeUpdateSub.unsubscribe();
    }
  }

  ngOnInit() {
    this.sourceData = this.getCurrentPageDataMode();

    this.workflowUpdatedSub = this.wSvr.workflowUpdated.subscribe(dataRegister => {
      if (!dataRegister) {
        return;
      }
      this.dataRegister = dataRegister;
    });

    this.flowNodeUpdateSub = this.wSvr.flowNodeUpdate.subscribe(data => {
      if (!data) { return; }
      this.flowNode = data;
    });

    const spBtn = this.componentData.extends.functionButton.find(x =>
      x.event == 'corrective' ||
      x.event == 'correctiveAudit' ||
      x.event == 'suspendProject' ||
      x.event == 'closedProject' ||
      x.event == 'startProject'
    );
    if (spBtn) {
      // 是否存在特殊的按钮，隐藏页面本身的按钮区域
      this.pageSvr.pageBtnShowOrHide$.next(true);
    }

    this.auditFinishSub = this.wSvr.auditFinish$.pipe(delay(500)).subscribe(() => {
      // 审核结束时发出的通知
      // 获取当前页面的审核组件
      const hasAuditCom = this.pageSvr.getTmpComItems().find(x => x.component.selector == 'audit');
      if (hasAuditCom) {
        this.resetAuditData(hasAuditCom);
      }
    });

  }

  ngAfterViewInit() {
    this.setAuthorityData();
  }

  resetAuditData(hasAuditCom) {
    const bindField = hasAuditCom.component.bindField;
    const auditValue = this.dataModel[bindField];
    if (auditValue && auditValue.isFinish) {
      for (const key in this.dataModel) {
        if (key.indexOf(bindField) > -1) {
          delete this.dataModel[key];
        }
      }

      this.dataModel[bindField] = '';
      this.wSvr.auditChanged$.next();
      this.wSvr.onSaveData$.next();

      location.reload();
    }

  }

  async buttonClickEvent(item: FunButton) {
    if (item.event === 'outside') {
      if (!item.linkUrl) {
        return this.msg.error('该按钮没有绑定页面');
      }
      window.location.href = item.linkUrl;
    }
    else if (item.event === 'inside') {
      if (!item.linkPage) {
        return this.msg.error('该按钮没有绑定页面');
      }
      this.router.navigate(['home/page/normal-page/' + item.linkPage]);
    }
    else if (item.event === 'switch') {
      // 开关按钮
      this.switchBtnClick();
    }
    else if (item.event === 'corrective') {
      // 更正
      await this.correctiveHandle();
    }
    else if (item.event === 'correctiveAudit') {
      await this.correctiveAuditHandle();
    }
    else if (item.event === 'suspendProject') {
      await this.dataRegisterSvr.updateDataRegisterStatus(this.dataRegister.id, 'suspend');
      this.msg.success('项目暂停成功！');
    }
    else if (item.event === 'closedProject') {
      await this.dataRegisterSvr.updateDataRegisterStatus(this.dataRegister.id, 'closed');
      this.msg.success('项目终止成功！');
      location.reload();
    }
    else if (item.event === 'startProject') {
      await this.dataRegisterSvr.updateDataRegisterStatus(this.dataRegister.id, 'opend');
      this.msg.success('项目开启成功！');
    }
  }

  private switchBtnClick() {
    const value = this.bindData;
    let flag = value == '是' ? true : false;
    flag = !flag;
    this.setBindData(flag ? '是' : '');
  }

  /**
   * 提交有审核的更正记录
   *
   */
  async correctiveAuditHandle() {
    try {
      // 更正审核
      const hasAuditCom = this.pageSvr.getTmpComItems().find(x => x.component.selector == 'audit');
      if (hasAuditCom) {
        const bindField = hasAuditCom.component.bindField;
        const auditData = this.dataModel[bindField];

        if (auditData) {
          // 已经提交过审核的逻辑
          const currentAuditItem = auditData.auditItems.find(x => x.isCurrent);
          if (currentAuditItem.isCorrective) {
            // 开启了更正审核的审核才提交
            let dataChangeLogStatus = '';
            if (currentAuditItem.conclusion == 'pass') {
              // 通过
              dataChangeLogStatus = DataChangeLogStatus.Pass;
            }
            else if (currentAuditItem.conclusion == 'return') {
              // dataChangeLogStatus = DataChangeLogStatus.UnPass;
              return;
            }
            else if (currentAuditItem.conclusion == 'unpass') {
              dataChangeLogStatus = DataChangeLogStatus.UnPass;
            }

            await this.auditDataChagneLog(dataChangeLogStatus);
            // 获取最新的dataRegister
            this.dataRegister = await this.dataRegisterSvr.getDataRegister(this.dataRegister.id);
            this.wSvr.notifyWorkflowUpdated(this.dataRegister);
            this.engineService.currentDataModel = {
              ... this.engineService.currentDataModel,
              ...this.dataRegister.data.fields
            };
          }

        }
        else {
          // 表示还没有提交变更申请的逻辑
          const log = this.generateDataChangeLog();
          log.status = DataChangeLogStatus.InReview;
          // 获取审核组件的数据值

          // 还原其他的数据值修改，只修改审核组件的数据值到dataregister
          // tslint:disable-next-line: forin
          for (const key in this.sourceData) {
            this.dataModel[key] = this.sourceData[key];
          }
          this.dataModel[bindField] = auditData;

          await this.dataChangeSvr.createDataChangeLog(log);
        }

        this.pageSvr.auditBtnClick$.next();
        // 审核是否全部提交，全部提交重置审核
        // this.resetAuditData(hasAuditCom);
        // 发通知给表格组件，发起新的查询
        this.dataChangeSvr.dataChangeLogUpdated$.next();
        this.handleSwitchBtn();
      }

    } catch (error) {
      ExceptionHandler.current.handleError(error);
    }

  }

  /**
   * 提交无审核的更正记录
   *
   */
  async correctiveHandle() {
    try {
      const valid = await this.validateComponents();
      if (!valid) {
        return;
      }
      let log = this.generateDataChangeLog();
      if (!log.data || Object.keys(log.data).length == 0) {
        this.msg.error('无数据变化！');
        return;
      }
      else {
        await this.dataChangeSvr.createDataChangeLog(log);
        this.msg.success('提交更正成功！');
        this.wSvr.workflowUpdated.next(this.dataRegister);
      }

      this.handleSwitchBtn();

      // 发通知给表格组件，发起新的查询
      this.dataChangeSvr.dataChangeLogUpdated$.next();
    } catch (error) {
      ExceptionHandler.current.handleError(error);
    }
  }

  handleSwitchBtn() {
    const switchBtn = this.componentData.extends.functionButton.find(x => x.event == 'switch');
    if (switchBtn) {
      this.switchBtnClick();
    }
  }

  generateDataChangeLog() {
    const log = new DataChangeLog();
    log.id = Tools.GetGuid();
    log.dataRegisterId = this.dataRegister.id;
    log.status = DataChangeLogStatus.Pass;
    log.orgId = this.orgId;
    log.operatorId = this.user.id;
    log.operatorName = this.user.name;
    log.status = DataChangeLogStatus.Pass;
    log.flowNodeId = this.flowNode.flowNodeId;
    log.data = this.getDataChangeLogData();

    return log;
  }

  getDataChangeLogData() {
    let changeData = {};
    for (let key in this.sourceData) {
      const sourceData = this.sourceData[key];
      const targetData = this.dataModel[key];

      const sKey = Md5.hashStr(JSON.stringify(sourceData)) as string;
      const tKey = Md5.hashStr(JSON.stringify(targetData)) as string;

      if (sKey != tKey) {
        changeData[key] = {
          sourceValue: sourceData,
          targetValue: targetData,
          updateTime: Date.now()
        }
      }
    }

    return changeData;
  }

  /**
   * 审核更正记录，通过，或不通过
   *
   */
  async auditDataChagneLog(stauts: string) {
    try {
      const inReviewDataList = await this.dataChangeSvr.queryDataChangeLog({
        dataRegisterId: this.dataRegister.id,
        status: DataChangeLogStatus.InReview
      });
      if (inReviewDataList.length > 0) {
        const inReviewData = inReviewDataList[0];
        await this.dataChangeSvr.updataDataChangeLogStatus(inReviewData.id, stauts);
      }

    } catch (error) {
      ExceptionHandler.current.handleError(error);
    }
  }

  getCurrentPageDataMode() {
    const tmpComItems = this.pageSvr.getTmpComItems();
    const resultObj = {};
    tmpComItems.forEach(tmpComItem => {
      const bindField = tmpComItem.component.bindField;
      if (bindField) {
        if (typeof (this.dataModel[bindField]) == 'object') resultObj[bindField] = JSON.parse(JSON.stringify(this.dataModel[bindField]));
        else resultObj[bindField] = this.dataModel[bindField];
      }
    });

    return resultObj;
  }

  /**
 * 校验当前页面的组件
 */
  async validateComponents() {
    const result = await this.engineService.validateComponents();
    if (result && result.length) {
      const msg = result.map(x => x.errorMsg).filter(x => x).join(',');
      this.msg.error(`验证失败${msg ? '【' + msg + '】' : ''}，请检查表单！`);
      return false;
    } else {
      return true;
    }
  }

}

interface FunButton {
  btnColor: string;
  event: 'switch' | 'inside' | 'outside';
  functionName: string;
  iconColor: string;
  linkUrl: string;
  linkPage: string;
}
